package dmt16.TelemetrySuit.Communication.PacketTypes
{
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	public final class DataMessage implements IPacket
	{
		private var _data:ByteArray;
		private var _checksum:uint;
		
		public function DataMessage(content:ByteArray,checksum:uint)
		{
			_data=content;
			_data.endian=Endian.LITTLE_ENDIAN;
			_checksum=checksum;
			if(_data==null)
				_data=new ByteArray();
		}
		
		public function get type():int
		{
			return PacketType.DATA_MESSAGE;
		}
		
		public function get dataLength():int
		{
			return _data.length;
		}		
		
		public function get checksum():uint
		{
			return _checksum;
		}
		
		public function set checksum(c:uint):void
		{
			_checksum=c;
		}
		
		public function validateChecksum():Boolean
		{
			var p:uint=_data.position;
			_data.position=0;
			var _c:uint=0;
			while(_data.bytesAvailable>1)
				_c^=_data.readUnsignedShort();
			if(_data.bytesAvailable==1)
				_c^=_data.readUnsignedByte();
			_data.position=p;
			return _c==_checksum;
		}
		
		public function updateChecksum():void
		{
			var p:uint=_data.position;
			_data.position=0;
			_checksum=0;
			while(_data.bytesAvailable>1)
				_checksum^=_data.readUnsignedShort();
			if(_data.bytesAvailable==1)
				_checksum^=_data.readUnsignedByte();
			_data.position=p;
		}
		
		public function outputBinary():ByteArray
		{
			updateChecksum();
			var output:ByteArray=new ByteArray();
			output.endian=Endian.LITTLE_ENDIAN;
			output.writeByte(0x01); // start
			output.writeByte(type);	//type
			output.writeShort(_data.length);	//length
			output.writeBytes(_data,0,_data.length);	//data	
			output.writeShort(_checksum);	//checksum
			output.writeByte(0x04);	//end
			return output;
		}
		
		public function resetDataPointer():void{
			_data.position=0;
		}
		
		public function readUint8():uint{
			return _data.readUnsignedByte();
		}
		
		public function readUint16():uint{
			return _data.readUnsignedShort();
		}
		
		public function readUint32():uint{
			return _data.readUnsignedInt();
		}
		
		public function readString():String
		{
			var startPos:uint=_data.position;
			var char:int;
			var result:String="";
			while(_data.bytesAvailable>0)
			{
				char=_data.readByte();
				if(char!=0)
					result+=String.fromCharCode(result);
				else
					return result;	
			}
			throw new Error("Error reading string, null character not found");
			_data.position=startPos;
			return null;
		}
	}
}